#pragma once

#include "SPD3D11Prerequisite.h"

namespace SP
{
	//-------------------------------------------------------------------------------------
	class DLL_EXPORT SPCamera
	{
	public:
		SPCamera();
		const	XMMATRIX GetViewMtx() const			{			return XMLoadFloat4x4(&m_mView);			}
		const	XMMATRIX GetProjMtx() const				{			return XMLoadFloat4x4(&m_mProj);				}
		const	XMMATRIX GetViewProjMtx() const		{			return GetViewMtx()*GetProjMtx();				}
		const	XMMATRIX GetViewInv() const				{			return XMLoadFloat4x4(&m_mViewInv);		}
		const	XMFLOAT3& GetEyePt()						{			return m_vEyePt;											}
		const	XMFLOAT3& GetLookatPt()					{			return m_vLookatPt;										}
		void		SetWindow( INT nWidth, INT nHeight );
		void		SetCamera(	const XMFLOAT3& vEye, 
										const XMFLOAT3& vLookAt, 
										const XMFLOAT3& vUp = XMFLOAT3( 0.0f, 1.0f, 0.0f ) );

		XMMATRIX GetOrthoMatrix(){ return XMLoadFloat4x4( &m_mOrthoMatrix ); }

		UINT GetWindowsWidth(){ return m_nWidth; }
		UINT GetWindowsHeight(){ return m_nHeight; }

	protected:
		XMFLOAT4X4		m_mView;
		XMFLOAT4X4		m_mProj;
		XMFLOAT4X4		m_mViewInv;    

		XMFLOAT3			m_vEyePt;
		XMFLOAT3			m_vLookatPt;

		UINT						m_nWidth;
		UINT						m_nHeight;

		XMFLOAT4X4		m_mOrthoMatrix;
	};

	//-------------------------------------------------------------------------------------
	class DLL_EXPORT SPModelViewerCamera : public SPCamera
	{
	public:
		SPModelViewerCamera();
		void Closer();
		void Further();
			   
		void OnBegin( int nX, int nY ); 
		void OnMove( int nX, int nY ); 
		void OnEnd(); 

		const XMMATRIX GetRotationMatrix()			
		{			
			return XMMatrixRotationQuaternion(XMLoadFloat4( &m_qNow ) );		
		}
		bool IsBeingDragged() const							
		{			
			return m_bDrag;
		}
		const XMFLOAT4 GetQuatNow() const			
		{			
			return m_qNow;
		}
		void SetQuatNow( const XMFLOAT4* q )		
		{			
			m_qNow = *q;	
		}

		static XMVECTOR	QuatFromBallPoints( const XMVECTOR vFrom, const XMVECTOR vTo );

	protected:
		void Update();

		XMFLOAT4X4	m_mRotation;

		FLOAT				m_fRadius;
		FLOAT				m_fEyeRadius;

		XMFLOAT4		m_qDown;
		XMFLOAT4		m_qNow;
		bool					m_bDrag;

		XMFLOAT3		m_vDownPt;
		XMFLOAT3		m_vCurrentPt;
		XMFLOAT3		ScreenToVector( float fScreenPtX, float fScreenPtY );
	};
}